package com.gitee.helioz.openai.api;

import com.gitee.helioz.openai.common.util.http.ContentTypeEnum;
import com.gitee.helioz.openai.common.util.http.HttpFilePart;
import com.gitee.helioz.openai.common.util.http.HttpProxyConfig;
import com.gitee.helioz.openai.common.util.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * 〈URLConnection实现类〉
 *
 * @author <a href="https://gitee.com/helioz">Morning Starr</a>
 */
@Slf4j
public class OpenAiURLConnectionServiceImpl extends BaseOpenAiServiceImpl {

    public OpenAiURLConnectionServiceImpl() {
        super();
    }

    public OpenAiURLConnectionServiceImpl(HttpProxyConfig httpProxyConfig) {
        super(httpProxyConfig);
    }

    @Override
    protected void initHttp() {
        // do nothing
    }

    @Override
    protected String sendGetRequest(String url) throws IOException {
        Map<String, String> headerMap = buildHeaderMap();
        log.debug("发送[GET]请求，URL=[{}]，设置请求头={}", url, headerMap);
        HttpURLConnection connection = buildHttpURLConnection(url);
        connection.setRequestMethod("GET");
        // 设置请求头
        if (headerMap != null && !headerMap.isEmpty()) {
            headerMap.forEach(connection::setRequestProperty);
        }
        int responseCode = connection.getResponseCode();
        log.debug("响应[GET]请求，URL=[{}]，responseCode={}", url, responseCode);
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String responseBody = HttpUtils.getResponseBody(connection);
            connection.disconnect();
            log.debug("响应[GET]请求，URL=[{}]，responseBody={}", url, responseBody);
            return responseBody;
        }
        HttpUtils.handleError(connection, responseCode);
        return null;
    }

    @Override
    protected String sendPostJsonRequest(String url, String jsonBody) throws IOException {
        Map<String, String> headerMap = buildHeaderMap();
        log.debug("发送[POST]请求，URL=[{}]，设置请求头={}, JSON BODY={}", url, headerMap, jsonBody);
        HttpURLConnection connection = buildHttpURLConnection(url);
        connection.setRequestMethod("POST");
        // 设置请求头
        if (headerMap != null && !headerMap.isEmpty()) {
            headerMap.forEach(connection::setRequestProperty);
        }
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setDoOutput(true);

        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(jsonBody.getBytes());
        outputStream.flush();
        outputStream.close();

        int responseCode = connection.getResponseCode();
        log.debug("响应[POST]请求，URL=[{}]，responseCode={}", url, responseCode);
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String responseBody = HttpUtils.getResponseBody(connection);
            connection.disconnect();
            log.debug("响应[POST]请求，URL=[{}]，responseBody={}", url, responseBody);
            return responseBody;
        }
        HttpUtils.handleError(connection, responseCode);
        return null;
    }

    @Override
    protected String sendPostFormData(String url, Map<String, Object> formMap, List<HttpFilePart> fileParts) throws IOException {
        Map<String, String> headerMap = buildHeaderMap();
        int fileSize = fileParts == null ? 0 : fileParts.size();
        log.debug("发送[POST FORM]请求，URL=[{}]，设置请求头={}, form={}, fileSize={}", url, headerMap, formMap, fileSize);
        HttpURLConnection connection = buildHttpURLConnection(url);
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);
        // 设置请求头
        if (headerMap != null && !headerMap.isEmpty()) {
            headerMap.forEach(connection::setRequestProperty);
        }
        OutputStream outputStream;
        // 方法内部flush
        if (fileSize > 0) {
            String boundary = "----MorningStarr_" + System.currentTimeMillis();
            connection.setRequestProperty("Content-Type", HttpUtils.CONTENT_TYPE_MULTIPART_PREFIX + boundary);
            outputStream = connection.getOutputStream();
            HttpUtils.writeMultipart(outputStream, formMap, fileParts, boundary);
        } else {
            connection.setRequestProperty("Content-Type", ContentTypeEnum.FORM_URLENCODED.getType());
            outputStream = connection.getOutputStream();
            HttpUtils.writeFormUrlEncoded(outputStream, formMap);
        }
        outputStream.close();
        // 响应
        int responseCode = connection.getResponseCode();
        log.debug("响应[POST FORM]请求，URL=[{}]，responseCode={}", url, responseCode);
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String responseBody = HttpUtils.getResponseBody(connection);
            connection.disconnect();
            log.debug("响应[POST FORM]请求，URL=[{}]，responseBody={}", url, responseBody);
            return responseBody;
        }
        HttpUtils.handleError(connection, responseCode);
        return null;
    }

    @Override
    protected String sendDeleteRequest(String url) throws IOException {
        Map<String, String> headerMap = buildHeaderMap();
        log.debug("发送[DELETE]请求，URL=[{}]，设置请求头={}", url, headerMap);
        HttpURLConnection connection = buildHttpURLConnection(url);
        connection.setRequestMethod("DELETE");
        // 设置请求头
        if (headerMap != null && !headerMap.isEmpty()) {
            headerMap.forEach(connection::setRequestProperty);
        }
        int responseCode = connection.getResponseCode();
        log.debug("响应[DELETE]请求，URL=[{}]，responseCode={}", url, responseCode);
        if (responseCode == HttpURLConnection.HTTP_OK) {
            String responseBody = HttpUtils.getResponseBody(connection);
            connection.disconnect();
            log.debug("响应[DELETE]请求，URL=[{}]，responseBody={}", url, responseBody);
            return responseBody;
        }
        HttpUtils.handleError(connection, responseCode);
        return null;
    }

    /**
     * 构建HttpURLConnection对象
     *
     * @param url 地址
     * @return HttpURLConnection
     * @throws IOException
     */
    private HttpURLConnection buildHttpURLConnection(String url) throws IOException {
        // 创建 HttpURLConnection 对象
        URL urlObj = new URL(url);
        if (this.getHttpProxyConfig() != null) {
            HttpProxyConfig httpProxyConfig = this.getHttpProxyConfig();
            // 设置代理
            Proxy proxy = new Proxy(httpProxyConfig.getType(), new InetSocketAddress(httpProxyConfig.getHost(), httpProxyConfig.getPort()));
            // 设置代理认证账号密码 见方法：buildHeaderMap
            return (HttpURLConnection) urlObj.openConnection(proxy);
        }
        return (HttpURLConnection) urlObj.openConnection();
    }

}
